#!/usr/bin/python2.4
#
# Copyright 2007 Dobromir Montauk. All Rights Reserved.

"""Test cases for data_processor.py
"""

__author__ = "dmontauk@gmail.com (Dobromir Montauk)"

import unittest
import datetime

from dashomatic import BadDataError
from dashomatic import data_processor

class DataProcessor_test(unittest.TestCase):
  def setUp(self):
    """We set up fairly hard data structures to test our functions
    against.
    """ 
    self.bad_headers = [3,2,"3","2",1]
    self.headers = [1]
    self.empty_dict = [{}]
    self.empty_list = []
    self.complex_dict = [{ 1  : "a",
                           2  : "b",
                          "3" : datetime.date(2000,1,1),
                          },
                         { 1  : datetime.date(2000,1,1),
                          "2" : 3,
                           3  : """hello, world""",
                          },
                         { 1  : """Wow, this \isn't a <h^rd>!! string "?"""
                          },
                        ]
    self.complex_list = [ [1,2,3,4,5,6,7,9,10,1,111],
                          ["hello world","yes","no",datetime.date(2000,1,1),],
                          [],
                          [None,]
                        ]
    
    self.simple_dict = [{ 1 : "a",
                          2 : "b",
                          3 : "c",
                          },
                        { 1 : "d",
                          2 : "e",
                          3 : "f",
                          },
                        { 1 : "g",
                          2 : "h",
                          3 : "i",
                          },
                        ]

    self.rollup_data = [  ["Date","Country","CustomerId","Visits","Purchases"],
                          ["2007-07-01","USA",100,0,0],
                          ["2007-07-01","USA",101,1,2],
                          ["2007-07-01","France",99,2,4],
                          ["2007-07-01","France",3,3,6],
                          ["2007-07-02","USA",100,3,0],
                          ["2007-07-02","USA",101,2,1],
                          ["2007-07-02","France",99,1,2],
                          ["2007-07-02","France",100,0,3],                                                                                                                                      
                        ]



  def testInsertOrGrowList(self):
    l = []
    l = data_processor.InsertOrGrowList(l,3,"item","")
    self.assertEquals(l,["","","","item"])
  
  def testInsertOrGrowListIndices(self):
    l = []
    self.assertRaises(AssertionError,
                      data_processor.InsertOrGrowList,[],-1,"item","")
                        
  def testListOfDictsToListOfLists(self):
    result = data_processor.ListOfDictsToListOfLists(self.complex_dict)
    # This test depends on know the order of keys - not good, but oh well.
    expected_result = [ [1,2,"3",3,"2"],
                        ["a","b",datetime.date(2000,1,1)],
                        [datetime.date(2000,1,1),"","","hello, world",3,],
                        ["""Wow, this \isn't a <h^rd>!! string "?"""],
                      ]
    self.assertEquals(result,expected_result)

  def testEmptyDictsToLists(self):
    result = data_processor.ListOfDictsToListOfLists(self.empty_dict)
    self.assertEquals(result,[[],[]]) # Empty headers, plus empty row?
    
  def testNormalizeEmptyList(self):
    result = data_processor.NormalizeListOfLists(self.empty_list)
    self.assertEquals(result,[])
    
  def testNormalizeListOfLists(self):
    result = data_processor.NormalizeListOfLists(self.complex_list)
    expected_result = [ [1,2,3,4,5,6,7,9,10,1,111],
                          ["hello world","yes","no",datetime.date(2000,1,1),
                            "","","","","","",""],
                          ["","","","","","","","","","",""],
                          [None,"","","","","","","","","",""]
                        ]
    self.assertEquals(result,expected_result)

  def testNormalizeListOfListsWithPadding(self):
    result = data_processor.NormalizeListOfLists(self.complex_list,
                                                    empty="N/A")
    expected_result = [ [1,2,3,4,5,6,7,9,10,1,111],
                          ["hello world","yes","no",datetime.date(2000,1,1),
                            "N/A","N/A","N/A","N/A","N/A","N/A","N/A"],
                          ["N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A",
                            "N/A","N/A","N/A"],
                          [None,"N/A","N/A","N/A","N/A","N/A","N/A","N/A",
                            "N/A","N/A","N/A"]
                        ]
    self.assertEquals(result,expected_result)
  
  def testNormalizeListOfListsStrict(self):
    self.assertRaises(BadDataError,
                      data_processor.NormalizeListOfLists,
                      self.complex_list,
                      strict=True)
                        
  def testListOfDictsToCsvStrict(self):
    self.assertRaises(BadDataError,
                      data_processor.ListOfDictsToCsv,
                      self.complex_dict,
                      strict=True
                      )
                      
  def testListOfDictsToCsvNoStrict(self):
    result = data_processor.ListOfDictsToCsv(self.complex_dict)
    expected_result = ( '1,2,3,3,2\r\n'
                        'a,b,2000-01-01,,\r\n'
                        '2000-01-01,,,"hello, world",3\r\n'
                        '"Wow, this \\isn\'t a <h^rd>!! string ""?",,,,\r\n')
    self.assertEquals(result,expected_result)

  def testListOfDictsToCsvWithBadHeaders(self):
    self.assertRaises(BadDataError,
                      data_processor.ListOfDictsToCsv,
                      self.complex_dict,
                      headers=self.bad_headers,
                      )
                      
  def testListOfDictsToCsvWithGoodHeaders(self):
    result = data_processor.ListOfDictsToCsv(self.complex_dict,
                                                headers=self.headers)
    expected_result = ( '1\r\n'
                        'a\r\n'
                        '2000-01-01\r\n'
                        '"Wow, this \\isn\'t a <h^rd>!! string ""?"\r\n')
    self.assertEquals(result,expected_result)


  def testListOfDictToCsvPadding(self):
    result = data_processor.ListOfDictsToCsv(self.complex_dict,empty="N/A")
    expected_result = ( '1,2,3,3,2\r\n'
                        'a,b,2000-01-01,N/A,N/A\r\n'
                        '2000-01-01,N/A,N/A,"hello, world",3\r\n'
                        '"Wow, this \\isn\'t a <h^rd>!! string ""?",N/A,N/A,'
                        'N/A,N/A\r\n')
    self.assertEquals(result,expected_result)

  def testNormalizeDataRange(self):
    results = data_processor.NormalizeDataRange([0,3.5,19,3837,None,37])
    expected_results = [0.0,0.1,0.5,100.0,0,1.0]
    self.assertEquals(results,expected_results)
    
  def testNormalizeDataRangeEmpty(self):
    results = data_processor.NormalizeDataRange([])
    expected_results = []
    self.assertEquals(results,expected_results)
  
  def testNormalizeDataRangeZeros(self):
    results = data_processor.NormalizeDataRange([0,0,0,None])
    expected_results = [0,0,0,0]
    self.assertEquals(results,expected_results)
        
  def testNormalizeDataRangeNegative(self):
    self.assertRaises(BadDataError,data_processor.NormalizeDataRange,
                      [-1,2,5,9,None])


  def testRollUpDataDateNoFilter(self):
    results = data_processor.RollUpData(self.rollup_data[1:],0,[3,4],{})
    expected_results = [["2007-07-01",6,12],
                        ["2007-07-02",6,6],]
    self.assertEquals(results,expected_results)

  def testRollUpDataCountryDateFilter(self):    
    results = data_processor.RollUpData(self.rollup_data[1:],1,[3,4],{0:"2007-07-01"})
    expected_results = [["USA",1,2],
                        ["France",5,10],]
    self.assertEquals(results,expected_results)

  def testRollUpDataCountryDateFilter2(self):  
    results = data_processor.RollUpData(self.rollup_data[1:],1,[3,4],{0:"2007-07-02"})
    expected_results = [["USA",5,1],
                        ["France",1,5],]
    self.assertEquals(results,expected_results)

  def testRollUpDataCustomerDateCountryFilter(self):
    filter_by = {0:"2007-07-01", 1:"USA"}
    results = data_processor.RollUpData(self.rollup_data[1:],2,[3,4],filter_by)
    expected_results = [[100,0,0],
                        [101,1,2],]
    self.assertEquals(results,expected_results)

  def testRollUpDataCustomerDateCountryFilter2(self):
    filter_by = {0:"2007-07-01", 1:"France"}
    results = data_processor.RollUpData(self.rollup_data[1:],2,[3,4],filter_by)
    expected_results = [[99,2,4],
                        [3,3,6],]
    results.sort()
    expected_results.sort()
    self.assertEquals(results,expected_results)

  def testRollUpDataCustomerNoFilter(self):
    results = data_processor.RollUpData(self.rollup_data[1:],2,[3,4],{})
    expected_results = [[100,3,3],
                        [101,3,3],
                        [99,3,6],
                        [3,3,6],]
    results.sort()
    expected_results.sort()
    self.assertEquals(results,expected_results)
    
  def testRollUpDataCustomerDateCountryMultipleFilter(self):
    filter_by = {0:"2007-07-01",1:["USA","France"]}
    results = data_processor.RollUpData(self.rollup_data[1:],2,[3,4],filter_by)
    expected_results = [[100,0,0],
                        [101,1,2],
                        [99, 2,4],
                        [ 3, 3,6],]
    results.sort()
    expected_results.sort()
    self.assertEquals(results,expected_results)

if __name__ == '__main__':
  suite = unittest.TestLoader().loadTestsFromTestCase(DataProcessor_test)
  unittest.TextTestRunner(verbosity=2).run(suite)  
